// Masyu.cpp : Defines the entry point for the console application.
//
//#include "Cell.h"
#include "Masyu3.h"

//#include <iostream>
//using namespace std;



int main(int argc, char *argv[])
{
	if (argc != 2) 
	{
		cout<<"Args != 2!"<<endl;
		//return 1;
	}
	
	//cout<<argv[1]<<endl;
	
	cout<<"MAIN FUNCTION WORKING!!!\n";
	
	//stateManage(argv[1]);
	if (1 == stateManage("input.txt")) return 1;	//this is a debug stub
	
	   
	//textReader(argv[1]);	  
	return 0;
}
//textReader reads only one string for input of white and black cells
int textReader(const char *argg, list<Cell*>& blackCells, list<Cell*>& whiteCells, Cell **myarr)
{
	cout<<"TEXT READER WORKING!!!\n";
	ifstream fin(argg);
	stringstream iss;
	string seg, strg;
	int ii;                 //iterator used for rows in myarr
	int zz;					//iter used for columns
	if (!fin)
	{
		cout<<"sorry! Ne fin :)"<<endl;
		return 1;
	}
	while (!fin.eof())
	{
		//cout<<"MARK1"<<endl;
		getline(fin, strg);
		if (strg == "B")
		{
			getline(fin, strg);
			iss.str(strg);
			while (iss>>ii)
			{
				iss>>zz;
				--ii;--zz;    //we decrement them to fit into array of m size. we have to increment them before final output
				//cout<<"MARK2"<<endl;
				myarr[ii][zz].setPos(ii, zz);
				//cout<<"MARK21"<<endl;
				blackCells.push_back(&myarr[ii][zz]);
				//cout<<"MARK22"<<endl;
			}
		}
		if (strg == "W")
		{
			getline(fin, seg);
			iss.str(seg);
			iss.clear();

			while (iss>>ii)
			{
				iss>>zz;
				--ii;--zz;
				//cout<<"MARK3"<<endl;
				myarr[ii][zz].setPos(ii, zz);
				whiteCells.push_back(&myarr[ii][zz]);
			}
		}
	}
	//cout<<"MARK4"<<endl;
	cout<<"Coordinates of black cells: \n";
	for (iter ia = blackCells.begin(); ia != blackCells.end(); ++ia)
	{
		//cout<<"MARK5"<<endl;
		cout<<*ia;
	}
	cout<<"\nCoordinates of white cells: \n";
	for (iter ia = whiteCells.begin(); ia != whiteCells.end(); ++ia)
	{
		//cout<<"MARK6"<<endl;
		cout<<*ia;
	}
	//cout<<"Here is blacklist INSIDE textreader (5,0): "<<blackCells.front()<<endl;
	return 0;
}

int stateManage(const char *argg)
{
	cout<<"STATE MANAGE WORKING!!!\n";
	Cell **myarr;
	const int M = 7;					// this magic number makes me think of it.
	const int N = M - 1; 
	myarr = new Cell *[M];				//we create a 2-dimension array. Can we use not default constructor here to initialize pos immediately?
	for (int j = 0; j < M; j++)
	{
		//cout<<"Starting to create "<<j<<" elements..."<<endl;
		myarr[j] = new Cell[M];
	}
	multimap<bool*, Cell*> objfinder;
	if (1 == initMultiset(myarr, N, objfinder)) return 1;		//make sure we send SIZE-1

	//DEBUG: checking we have different addresses
/*	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < m; j++)
		{
			cout<<"myarr["<<i<<"]["<<j<<"] = "<<&myarr[i][j]<<endl;
		}
	}
*/	
	
	
	list<Cell*> blackCells, whiteCells;
	if (1 == textReader(argg, blackCells, whiteCells, myarr)) return 1;			//after doing it we got lists of objects of black and white cells
	cout<<"WE ARE BACK IN STATE MANAGER"<<endl;
	
	//whiteProcessing(whiteCells, myarr);

		
	
	for (int i = 0; i < M; i++) {
		delete []myarr[i];
	}
	delete []myarr;
	/*
	//THIS BLOCK IS TO CHECK IF LISTS ARE FILLED CORRECTLY
	typedef list<Cell>::iterator iter;
	cout<<"Coordinates of black cells: \n";
	for (iter ia = blackCells.begin(); ia != blackCells.end(); ++ia)
	{

		cout<<*ia;
		//cout<<"x and y coordinates: "<<ia->getPos();
	}
	cout<<"\nCoordinates of white cells: \n";
	for (iter ia = whiteCells.begin(); ia != whiteCells.end(); ++ia)
	{

		cout<<*ia;
		//cout<<"x and y coordinates: "<<ia->getPos();
	}
	*/
	return 0;
}

int blackProcessing(list<Cell *> &blCells, Cell **myarray)
{
	return 0;
}


int whiteProcessing(list<Cell *> &whCells, Cell **myarray)
{
	Cell* tempCell;
	//pair<int, int> coordinates;
	for (iter it = whCells.begin(); it != whCells.end(); it++)
	{
		tempCell = *it;
		//coordinates = tempCell->getPos();
		int res = tempCell->checkDirectionSwitch(WHITE);
		if (1 == res) return 1;
		if ( res != 0)		
		{
			tempCell->setDirectionToBlocked(res);
			tempCell->setCondition(READY);
			decomposite(tempCell->checkDirectionSwitch(WHITE));
		}


			

	}
	return 0;
}


int initMultiset(Cell **cellarr, const int N, multimap<bool*, Cell*>& objcontainer)
{
	for (int i = 0; i <= N; i++)							//this sets shared borders between cells and status "blocked" to edge cells' borders
	{
		for (int j = 0; j <= N; j++)
		{
			if (j != 0)
			{
				if (j == N) cellarr[i][j].setDirectionToBlocked(DOWN);		//sets bottom edge to blocked
				delete cellarr[i][j].getDirection().up;
				cellarr[i][j].copyDirection(UP, cellarr[i][j-1].getDirection().down);	//sets shared horizontal borders
			} else
			{
				cellarr[i][j].setDirectionToBlocked(UP);					//sets upper edge to blocked
			}

			if (i != 0)
			{
				if (i == N) cellarr[i][j].setDirectionToBlocked(RIGHT);		//sets right edge to blocked
				delete cellarr[i][j].getDirection().left;
				cellarr[i][j].copyDirection(LEFT, cellarr[i-1][j].getDirection().right);		//sets vertical shared borders
			} else
			{
				cellarr[i][j].setDirectionToBlocked(LEFT);					//sets left edge to blocked
			}
		}
	}
	

	
	for (int i = 0; i <= N; i++)
	{
		for (int j = 0; j <= N; j++)
		{
			objcontainer.insert(make_pair(cellarr[i][j].getDirection().down, &cellarr[i][j])); 	//we place direction fields' pointers of array object into map as a key, address of array object as a value
			objcontainer.insert(make_pair(cellarr[i][j].getDirection().up, &cellarr[i][j])); 
			objcontainer.insert(make_pair(cellarr[i][j].getDirection().left, &cellarr[i][j])); 
			objcontainer.insert(make_pair(cellarr[i][j].getDirection().right, &cellarr[i][j])); 
		}
	}
	/*
	cout<<"Here is what multimap says:"<<endl;
	cout<<objfinder.find(cellarr[3][3].getDirection().left)->first<<endl;
	cout<<objfinder.find(cellarr[2][3].getDirection().right)->first<<endl;
	cout<<objfinder.find(cellarr[3][3].getDirection().up)->first<<endl;
	cout<<objfinder.find(cellarr[3][2].getDirection().down)->first<<endl;
	*/
	return 0;
}


int getMapObject(multimap<bool*, Cell*>& objfndr)
{
	return 0;
}